package com.md.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.md.base.exception.ServerException;
import com.md.value.constants.Constants;
import com.md.value.enums.ErrorEnum;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author 刘骄阳
 * 2022-03-11 17:50
 */
@Slf4j
@UtilityClass
public class EncryptionUtils {
  private static final String JWT_SECRET_KEY = "asd";

//  public static void createSecurity() {
//    // 生成RSA密钥对
//    KeyPairGenerator keyGen = null;
//    try {
//      keyGen = KeyPairGenerator.getInstance("RSA");
//    } catch (NoSuchAlgorithmException e) {
//      throw new RuntimeException(e);
//    }
//    keyGen.initialize(2048); // 设置密钥长度
//    KeyPair keyPair = keyGen.generateKeyPair();
//    PublicKey publicKey = keyPair.getPublic();
//    PrivateKey privateKey = keyPair.getPrivate();
//    publicKey.getAlgorithm()
//    // 使用公钥加密数据
//    Cipher encryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // 算法和模式
//    encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
//
//    byte[] plaintextBytes = "This is a secret message".getBytes("UTF-8");
//    byte[] encryptedBytes = encryptCipher.doFinal(plaintextBytes);
//  }
//
//  public static <T> T privateSecurityDecryption(Class<T> clazz, final String privateKey, PrivateKey privateKey1) {
//    Cipher decryptCipher = null;
//    try {
//      decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//      decryptCipher.init(Cipher.DECRYPT_MODE, privateKey1);
//      byte[] decryptedBytes = decryptCipher.doFinal(encryptedBytes);
//      String decryptedText = new String(decryptedBytes, "UTF-8");
//    } catch (Exception e) {
//      throw ServerException.build(ErrorEnum.DECODING_ERROR, e);
//    }
//
//  }


  /**
   * MD5加密字符串
   *
   * @param str 要加密的字符串
   * @return 加密后的字符串
   */
  public static String md5Encryption(final String str) {
    return DigestUtils.md5Hex(str);
  }

  /**
   * AES加密字符串
   *
   * @param salt  盐值
   * @param value 要加密的字符串
   * @return 加密后的字符串
   */
  public static String aesEncryption(final String salt, final String value) {
    return AES.encoding(salt, value);
  }

  /**
   * AES解密字符串
   *
   * @param salt  盐值
   * @param value 要解密的字符串
   * @return 解密后的字符串
   */
  public static String aesDecryption(final String salt, final String value) {
    return AES.decoding(salt, value);
  }

  /**
   * MD5加密字符串
   *
   * @param str  要加密的字符串
   * @param salt 盐值
   * @return 加密后的字符串
   */
  public static String md5Encryption(final String str, final String salt) {
    return DigestUtils.md5Hex(str + Constants.UNDERLINE + salt);
  }

  public static String jwtEncryption(final String sub,
                                     final Long expirationTime,
                                     final TimeUnit timeUnit) {
    return JWT.create()
      .withSubject(sub)
      .withIssuedAt(new Date())
      .withExpiresAt(new Date(System.currentTimeMillis() + timeUnit.toMillis(expirationTime)))
      .sign(Algorithm.HMAC256(JWT_SECRET_KEY)); // 使用 HMAC SHA-256 签名算法
  }

  public static String jwtDecrypt(final String token) {
    return JWT.require(Algorithm.HMAC256(JWT_SECRET_KEY))
      .build()
      .verify(token) // 验证并解析 JWT
      .getSubject(); // 获取用户信息
  }

  private static final class AES {
    private static final String ALGORITHM = "AES";

    public static String encoding(final String salt, final String value) {
      SecretKeySpec secretKeySpec = new SecretKeySpec(salt.getBytes(StandardCharsets.UTF_8), ALGORITHM);
      try {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        // 加密过程
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        byte[] encryptedValue = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedValue);
      } catch (Exception e) {
        log.error("AES加密失败: {}", e.getMessage(), e);
        throw ServerException.build(ErrorEnum.ENCODING_ERROR);
      }
    }

    public static String decoding(final String salt, final String value) {
      SecretKeySpec secretKeySpec = new SecretKeySpec(salt.getBytes(StandardCharsets.UTF_8), ALGORITHM);
      try {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        // 解密过程
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        byte[] decryptedValue = cipher.doFinal(Base64.getDecoder().decode(value));
        return new String(decryptedValue, StandardCharsets.UTF_8);
      } catch (Exception e) {
        log.error("AES解密失败: {}", e.getMessage(), e);
        throw ServerException.build(ErrorEnum.DECODING_ERROR);
      }
    }
  }

}
